package org.third.java.jcf;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import java.io.IOException;
import java.security.Key;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;

class LambdaExceptionUtil {

	@FunctionalInterface
	public interface Function_WithException<T, R, E extends Exception> {
		R apply(T t) throws E;
	}

	@FunctionalInterface
	public interface Consumer_WithException<T, E extends Exception> {
		void apply(T t) throws E;
	}

	public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithException<T, R, E> function)
			throws E {
		return t -> {
			try {
				return function.apply(t);
			} catch (Exception exception) {
				throwActualException(exception);
				return null;
			}
		};
	}

	public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithException<T, E> consumer) throws E {
		return t -> {
			try {
				consumer.apply(t);
			} catch (Exception ex) {
				throwActualException(ex);
			}
		};
	}

	private static <E extends Exception> void throwActualException(Exception exception) throws E {
		throw (E) exception;
	}

}

public class AesTest {
	public static final String KEY_ALGORITHM = "AES";
	public static final String CIPHER_ALGORITHM = "AES";

	public static SecretKey initkey() throws Exception {

		// c 实例化密钥生成器
//      Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//      KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM, "BC");
		KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
		// c初始化 初始化密钥生成器，AES要求密钥长度为128位、192位、256位
//        kg.init(256); 
		kg.init(256);
		// A 生成密钥
		SecretKey secretKey = kg.generateKey();
		// A 获取二进制密钥编码形式
		return secretKey;
		// c 为了便于测试，这里我把key写死了，如果大家需要自动生成，可用上面注释掉的代码
//        return new byte[] { 0x08, 0x08, 0x04, 0x0b, 0x02, 0x0f, 0x0b, 0x0c,
//                0x01, 0x03, 0x09, 0x07, 0x0c, 0x03, 0x07, 0x0a, 0x04, 0x0f,
//                0x06, 0x0f, 0x0e, 0x09, 0x05, 0x01, 0x0a, 0x0a, 0x01, 0x09,
//                0x06, 0x07, 0x09, 0x0d };
	}

	public static byte[] encrypt(byte[] data, String ivStr) throws Exception {
		// c 还原密钥
//        Key k=toKey(key);
		Key k = initkey();
//		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
		// X 初始化，设置为加密模式
//		IvParameterSpec iv = new IvParameterSpec(ivStr.getBytes("utf-8"));
		cipher.init(Cipher.ENCRYPT_MODE, k);
		// c 执行操作
		return cipher.doFinal(data);
	}

	private static final ObjectMapper objectMapper = new ObjectMapper();

	public static void main(String[] args) throws Exception {
//		encrypt("test".getBytes(), "0123456789012345");

		LambdaExceptionUtil.rethrowConsumer(Test::getName);
		LambdaExceptionUtil.rethrowConsumer(t -> {
			throw new Exception();
		});

		Optional<String> str = Optional.ofNullable("test");
		str.map(featureStr -> {
			try {
				return objectMapper.readValue(featureStr, Test.class);
			} catch (IOException e) {
				return Optional.empty();
			}
		});

	}
}

class Test {
	public String getName() {
		return "xxxx";
	}

	public String getNameWithException() throws IOException {
		if (1 == 1) {
			throw new IOException();
		}
		return "xxxx";
	}
}
